(function () {
	//条件类型绝大部分场景下会和泛型一起使用，我们知道，泛型参数的实际类型会在实际调用时才被填充（类型别名中显式传入，或者函数中隐式提取），而条件类型在这一基础上，可以基于填充后的泛型参数做进一步的类型操作，比如这个例子：
	type LiteralType<T> = T extends string ? 'string' : 'other';

	type Res1_0 = LiteralType<'lys'>; // string
	type Res2_0 = LiteralType<599>; //other

	//条件类型中也常见多层嵌套
	type LiteralType1<T> = T extends string
		? 'string'
		: T extends number
		? 'number'
		: T extends boolean
		? 'boolean'
		: T extends null
		? 'null'
		: T extends undefined
		? 'undefined'
		: never;

	type Res1 = LiteralType1<'lys'>; // 'string'
	type Res2 = LiteralType1<599>; // 'number'
	type Res3 = LiteralType1<true>; // 'boolean'

	function universalAdd<T extends number | bigint | string>(x: T, y: T) {
		return x + (y as any);
	}

	//当我们调用这个函数时，由于两个参数都引用了泛型参数 T ，因此泛型会被填充为一个联合类型：
	universalAdd(599, 1); // T 填充为 599 | 1

	// universalAdd(599, '1'); //我理解对泛型的推导是从左向右进行，universalAdd(599, 1) 会在第一个参数推导出 599 类型，然后在第二个参数进一步扩充这个类型，尝试找到一个同时满足这两个参数类型的类型（尝试在 number 下扩展，最终扩展为 599 | 1），universalAdd(599, "1") 这种情况就是无法进行合法扩展了

	universalAdd('lys', '599'); // T 填充为 'linbudu' | '599'

	//我们知道同一基础类型的字面量联合类型，其可以被认为是此基础类型的子类型，即 599 | 1 是 number 的子类型。
	//  升级：增加条件类型
	type LiteralToPrimitive<T> = T extends number ? number : T extends bigint ? bigint : T extends string ? string : never;

	function universalAdd1<T extends number | bigint | string>(x: T, y: T): LiteralToPrimitive<T> {
		return x + (y as any);
	}
	universalAdd1(899, 1); // number
	universalAdd1(10n, 10n); // bigint
	universalAdd1('linbudu', '599'); // string

	//条件类型还可以用来对更复杂的类型进行比较，比如函数类型：
	type Func = (...args: any[]) => any;

	type FunctionConditionType<T extends Func> = T extends (...args: any[]) => string ? 'A string return func!' : 'A non-string return func!'; //与此同时，存在泛型约束和条件类型两个 extends 可能会让你感到疑惑，但它们产生作用的时机完全不同，泛型约束要求你传入符合结构的类型参数，相当于参数校验。而条件类型使用类型参数进行条件判断（就像 if else），相当于实际内部逻辑。

	type StringResult = FunctionConditionType<() => string>; //  "A string return func!"
	type StringResult1 = FunctionConditionType<() => boolean>; // 'A non-string return func!';
	type StringResult2 = FunctionConditionType<() => number>; // 'A non-string return func!';
})();
